import cocos, pyglet, os, glob
from cocos.menu import *
from cocos.scenes import *
from cocos.director import director
from cocos.actions import *

import game, backgrounds, config, cutscenes, models, sound, gui
from config import current as conf


class BaseMenu(Menu):
    """Base menu to define custom fonts"""
    def __init__(self, title, menu_items):
        super(BaseMenu, self).__init__(title)
        self.menu_valign = CENTER
        for font in (self.font_item, self.font_item_selected, self.font_title):
            font['font_name'] = conf.title_font
            font['color'] = (255, 255, 255, 255)
            font['font_size'] = 40
        self.font_item_selected['color'] = (60, 0, 0, 255)
        self.font_title['font_size'] = 96
        self.create_menu(menu_items, shake(), shake_back() )

class MainMenu(BaseMenu):
    def __init__(self):
        super(MainMenu, self ).__init__('Necropoli', [
            MenuItem('New Game', self.on_new_game),
            MenuItem('Load Game', self.on_load_game),
            MenuItem('Options', self.on_options),
            MenuItem('Credits', self.on_credits),
            MenuItem('Quit Game', self.on_quit)])

    def on_load_game(self):
        # this is a hack to get the load screen to refresh to new files
        self.parent.layers = self.parent.layers[:-1] + (LoadGameMenu(), )
        self.parent.switch_to(2)

    def on_new_game(self):
        try:
            level1 = os.path.join(conf.levels_dir, "level1"+conf.file_extension)
            state = models.load(level1)
            state.new_game = True
        except:
            print "could not load first level, using test data instead..."
            state = models.TestState()
        self.parent.parent.start(state)

    def on_options(self):
        self.parent.switch_to(1)

    def on_credits(self):
        director.push(FadeTransition(cutscenes.Credits(), conf.short_transition_time))
        
    def on_quit(self):
        pyglet.app.exit()

class OptionsMenu(BaseMenu):
    def __init__(self):
        super(OptionsMenu, self ).__init__("Options", [
            ToggleMenuItem('Fullscreen: ',
                           director.window.set_fullscreen,
                           director.window.fullscreen),
            MultipleMenuItem('Difficulty: ', self.on_config, config.list, 1),
            MenuItem('Back', self.on_quit )])

    def on_quit(self):
        self.parent.switch_to(0)

        

    def on_config(self, new):
        config.set_config(new)

class LoadGameMenu(BaseMenu):
    def __init__(self):
        super(LoadGameMenu, self ).__init__('Load Game', [])
        items = []
        save_file_pattern = os.path.join(conf.save_dir, "*"+conf.file_extension)
        load = lambda s: (lambda: self.on_load(s))
        for f in glob.iglob(save_file_pattern):
            name = os.path.split(f)[1].split(".")[0]
            items.append(MenuItem(name, load(f)))
        items.append(MenuItem('Back', lambda: self.parent.switch_to(0)))
        self.create_menu(items)

    def on_load(self, filename):
        self.parent.switch_to(0)
        
        # this is a hack to get the load screen to refresh to new files
        self.parent.layers = self.parent.layers[:-1] + (None, )
        self.parent.parent.start(models.load(filename))

    def on_quit(self):
        self.parent.switch_to(0)

class MenuScene(cocos.scene.Scene):
    def __init__(self):
        super(MenuScene, self).__init__()
        self.add(cocos.layer.MultiplexLayer(MainMenu(), OptionsMenu(), LoadGameMenu()), z=2)
        
        # show an animated background that zooms/rotates slowly
        bg = backgrounds.ImageLayer('graffiti.jpg')
        r = (RotateBy(10, 30)|ScaleBy(1.5,30))
        bg.do(Repeat(r+Reverse(r)))
        self.add(bg, z=0)

        # start the menu BG music
        sound.start_menu()

    def start(self, state):
        if state.new_game:
            next = FadeTransition(cutscenes.Intro(game.GameScene(state)), conf.long_transition_time)
        else:
            next = FadeTransition(game.GameScene(state), conf.long_transition_time)
        director.push(next)

    def on_enter(self):
        super(MenuScene, self).on_enter()
        sound.start_menu()

class InGameMenu(BaseMenu):
    def __init__(self):
        super(InGameMenu, self ).__init__('', [
            MenuItem('Resume', lambda: self.parent.parent.hide_menu()),
            ToggleMenuItem('Fullscreen: ',
                           director.window.set_fullscreen,
                           director.window.fullscreen),
            MenuItem('Save', lambda: self.parent.switch_to(1)),
            MenuItem('Quit', director.pop),
            ])

    is_event_handler = True
    def on_key_press (self, key, modifiers):
        if key == pyglet.window.key.ESCAPE:
            self.parent.parent.hide_menu()
            return True
        return super(InGameMenu, self).on_key_press(key, modifiers)

class InGameMenuFileSelect(BaseMenu):
    def __init__(self, state):
        self.state = state
        self.filename = "%sAD"%state.current_year
        super(InGameMenuFileSelect, self ).__init__('', [
            EntryMenuItem("", self.on_edit, self.filename ),
            MenuItem('Save', self.on_save),
            MenuItem('Cancel', lambda: self.parent.switch_to(0)),
            ])

    def on_edit(self, new):
        self.filename = new

    def on_save(self):
        path = os.path.join(conf.save_dir, self.filename+conf.file_extension)
        self.state.new_game = False
        self.state.save(path)
        self.parent.switch_to(0)

    is_event_handler = True
    def on_key_press (self, key, modifiers):
        if key == pyglet.window.key.ESCAPE:
            self.parent.parent.hide_menu()
            return True
        return super(InGameMenuFileSelect, self).on_key_press(key, modifiers)

class InGameMenuLayer(cocos.layer.Layer):
    """Show the in-game menu as an overlay"""
    def __init__(self, state):
        super(InGameMenuLayer, self).__init__()
        self.state = state

        self.button = gui.ClickableLabel("[Menu]", self.show_menu, (10, 600-30))
        self.add(self.button, z = -1)

    def show_menu(self):
        self.add(gui.ControlCatcherLayer(), z = 0)
        self.add(cocos.layer.ColorLayer(0,0,0,200), z = 1)
        self.add(cocos.layer.MultiplexLayer(
            InGameMenu(),
            InGameMenuFileSelect(self.state),
            ), z = 2)
        
    def hide_menu(self):
        for child in self.get_children():
            if child != self.button:
                self.remove(child)

    is_event_handler = True
    def on_key_press (self, key, modifiers):
        if key == pyglet.window.key.ESCAPE:
            self.show_menu()
            return True
        return False
